package com.cloudbroker.bcs.platform.dav.middle.aspect;

import com.cloudbroker.bcs.common.emoji.EmojiParser;
import com.cloudbroker.bcs.common.util.ReflectionUtil;
import com.cloudbroker.bcs.common.util.StringUtil;
import com.cloudbroker.bcs.common.util.ValueUtil;
import com.cloudbroker.bcs.common.validatioin.annotation.RichText;
import com.cloudbroker.bcs.common.validatioin.annotation.SensitiveWord;
import com.cloudbroker.bcs.platform.dav.common.config.ConfigValues;
import com.cloudbroker.bcs.platform.dav.middle.util.HtmlRegexpUtil;
import com.cloudbroker.bcs.platform.dav.middle.util.SensitiveWordUtil;
import com.cloudbroker.bcs.platform.dav.middle.util.ViewpointMsgFormatUtil;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by xuyn15828 on 2016/4/21.
 */
public class OpenApiDataParseAspect {
    
    public Object parseData(ProceedingJoinPoint pjp) throws Throwable {
        Object[] objAry = pjp.getArgs();
        if (null != objAry && 0 != objAry.length) {
            for (Object obj : objAry) {
                if (null != obj) {
                    Class<?> objClazz = obj.getClass();
                    Map<String, Field> fieldNameMap = ReflectionUtil.listAllFields(null, objClazz);
                    for (Map.Entry<String, Field> entry : fieldNameMap.entrySet()) {
                        Class<?> fieldType = entry.getValue().getType();
                        if (String.class == fieldType) {
                            String value = ValueUtil.getString(ReflectionUtil.getValue(obj, entry.getKey()));
                            //为空字符串过滤
                            if (StringUtil.isBlank(value)) {
                                ReflectionUtil.setValue(obj, entry.getKey(), "");
                            } else {
                                //emoji表情过滤
                                ReflectionUtil.setValue(obj, entry.getKey(), parseEmojiCode(value));
                                if (entry.getValue().isAnnotationPresent(RichText.class)) {
                                    //富文本过滤
                                    ReflectionUtil.setValue(obj, entry.getKey(), ViewpointMsgFormatUtil.formatContext(stripXSS(value)));
                                } else {
                                    //不是富文本，过滤html标签
                                    ReflectionUtil.setValue(obj, entry.getKey(), stripHTML(value));
                                }
                                if(entry.getValue().isAnnotationPresent(SensitiveWord.class)) {
                                    Set<String> sensitiveSet = SensitiveWordUtil.getSensitiveWord();
                                    String after = SensitiveWordUtil.replaceSensitiveWord(value, 2, "*",SensitiveWordUtil.addSensitiveWordToHashMap(sensitiveSet));
                                    ReflectionUtil.setValue(obj, entry.getKey(), after);
                                }
                            }
                        }
                    }
                }
            }
        }
        return pjp.proceed();
    }
    
    private String stripXSS(String value) {
        String avoidTag = ConfigValues.XSS_AVOID_TAG;
        List<String> black = Arrays.asList(avoidTag.split(","));
        //过滤黑名单标签
        for(String s : black){
            value = HtmlRegexpUtil.fiterHtmlTag(value,s);
        }
        //过滤不符合的属性值
        avoidTag = ConfigValues.XSS_AVOID_VALUE;
        black = Arrays.asList(avoidTag.split(","));
        for(String a : black){
            Pattern patttern = Pattern.compile(a + "=[\"|'](.*?)[\"|']", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = patttern.matcher(value).replaceAll("");
        }
        //过滤空字符串
        value = value.replaceAll("\0", "");
        
        Pattern scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
        
        scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");       
        
        scriptPattern = Pattern.compile("alert\\(.*?\\)", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
        
        scriptPattern = Pattern.compile("<%@(.*?)%>", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
        
        scriptPattern = Pattern.compile("AllowScriptAccess=[\"|'](.*?)[\"|']", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("AllowScriptAccess=\"sameDomain\"");
        
        return value;
    }
    
    private String stripHTML(String value) {
        if (HtmlRegexpUtil.hasSpecialChars(value)) {
            return HtmlRegexpUtil.filterHtml(value);
        }
        return value;
    }
    
    private String parseEmojiCode(String value) {
        String temp = null;
        for (int i = 0; i < value.length(); i++) {
            temp = value;
            value = EmojiParser.parseToHtmlDecimal(value);
            if (value.equals(temp)) {
                break;
            }
        }
        return value;
    }
}
